package com.xyy.saas.payment.payment.core.service;

import com.alibaba.fastjson.JSON;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.bo.PrepayBo;
import com.xyy.saas.payment.cores.enums.PaySceneEnum;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.dao.mapper.PrePayOrderMapper;
import com.xyy.saas.payment.dao.model.PrePayOrder;
import com.xyy.saas.payment.payment.core.dto.PrepayDto;
import com.xyy.saas.payment.util.ConcatStringUtil;
import com.xyy.saas.payment.util.JSONUtils;
import com.xyy.saas.payment.util.LeafUtil;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @Author: wuqiongda
 * @Date: 2019/12/17 10:41
 */
@Service
public class PrePayOrderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(PrePayOrderService.class);

    @Autowired
    private PrePayOrderMapper prePayOrderMapper;

    @Autowired
    private LeafUtil leafUtil;

    public List<PrePayOrder> queryByPayNos(List<String> payNos) {
       return prePayOrderMapper.getPrePayOrderByPayNos(payNos);
    }

    public int createPrePayOrder(PrePayOrder prePayOrder) throws PaymentException {
        if(prePayOrder==null){
            throw  new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), ResultCodeEnum.PARAM_ERROR.getMsg());
        }

        try{
            int count = prePayOrderMapper.insertSelective(prePayOrder);
            return count;
        }
        catch(Exception e){
            LOGGER.error(e.getMessage(), e);
        }
        return 0;
    }

    public PrepayBo prepayOrderByPrepayDto(PrepayDto prepayDto) throws PaymentException {
        PrepayBo prepayBo = new PrepayBo();
        String payNo = leafUtil.getSnowflakeId();

        if(payNo == null) {
            LOGGER.error("PrePayOrderService prepay get id from leaf is error prepayDto:{}", JSON.toJSON(prepayDto));
            throw new PaymentException(ResultCodeEnum.SYSTEM_BUSY_ERROR);
        }

        Map<String,String> extraMap = JSONUtils.parse2Map(prepayDto.getExtra(), String.class, String.class);

        if(extraMap == null) {
            extraMap = new HashMap<>(8);
        }

        extraMap.put("body", prepayDto.getBody());
        extraMap.put("subject", prepayDto.getSubject());

        if(!extraMap.containsKey("payScene")) {
            extraMap.put("payScene", PaySceneEnum.ONLINE_PAY.getCode());
        }

        PrePayOrder prePayOrder = new PrePayOrder();
        prePayOrder.setAmount(prepayDto.getAmount());
        prePayOrder.setBusinessOrderNo(prepayDto.getBusinessOrderNo());
        prePayOrder.setBusinessType(prepayDto.getBusinessType());
        prePayOrder.setBusinessOrderType(prepayDto.getBusinessOrderType());
        prePayOrder.setCallbackAddress(prepayDto.getCallbackUrl());
        prePayOrder.setCreateTime(new Date());
        prePayOrder.setPayNo(payNo);
        prePayOrder.setReceiverId(prepayDto.getUserId());
        prePayOrder.setTimeExpire(prepayDto.getTimeExpire());
        prePayOrder.setPayer(prepayDto.getPayerName());
        prePayOrder.setExtra(JSONUtils.toJSON(extraMap));
        prePayOrder.setPayer(prepayDto.getPayerId());
        prePayOrder.setContractCode(prepayDto.getContractCode());
        int count = createPrePayOrder(prePayOrder);

        if(count < 1) {
            LOGGER.error("PrePayOrderService prepay createPrePayOrder error prePayOrder:{}", JSON.toJSON(prePayOrder));
            throw new PaymentException(ResultCodeEnum.SYSTEM_BUSY_ERROR);
        }

        prepayBo.setPayNo(payNo);
        prepayBo.setUserId(prepayDto.getUserId());
        return prepayBo;
    }

    public List<PrePayOrder> getPrePayOrderByBusinessOrderNo(String businessOrderNo){
        return prePayOrderMapper.selectByBusinessOrderNo(businessOrderNo);
    }

    /**
     * 根据单号模糊查询
     * @param businessOrderNo
     * @return
     */
    public List<PrePayOrder> likePrePayOrderByBusinessOrderNo(String businessOrderType, String businessOrderNo){
        List<PrePayOrder> prePayOrders = prePayOrderMapper.selectByBusinessOrderNo(businessOrderNo);

        if(!CollectionUtils.isEmpty(prePayOrders)) {
            return prePayOrders;
        }

        List<PrePayOrder> result = new ArrayList<>();
        int start = NumberUtils.INTEGER_ONE;
        int size = 30;

        while(true) {
            List<PrePayOrder> subResult = prePayOrderMapper.
                    listByBusinessOrderNo(ConcatStringUtil.addIntegerPrefix(NumberUtils.INTEGER_ONE, start, businessOrderNo, size));

            if(CollectionUtils.isEmpty(subResult)) {
                break;
            }

            result.addAll(subResult);
            start += size;
        }

        return !CollectionUtils.isEmpty(result) ? result : prePayOrderMapper.likeByBusinessOrderNo(businessOrderType, businessOrderNo);
    }

    public PrePayOrder getPrePayOrderByPayNo(String payNo){
        return prePayOrderMapper.getPrePayOrderByPayNo(payNo);
    }
}
